package org.chenwang.projects.ehcacheaws;

import org.jets3t.service.security.AWSCredentials;

import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.Status;
import net.sf.ehcache.event.CacheEventListener;

public abstract class AmazonS3CacheReplicator implements CacheEventListener {
	
	protected Status status;
	
	protected String bucketName;
	
	protected String pathName;
	
	protected String pathSeparator;
	
	protected AWSCredentials credentials;

	public AmazonS3CacheReplicator(String bucketName, String pathName, 
			String pathSeparator, AWSCredentials credentials) {
		super();
		this.bucketName = bucketName;
		this.pathName = pathName;
		this.pathSeparator = pathSeparator;
		this.credentials = credentials;
		this.status = Status.STATUS_ALIVE;
	}

	@Override
	public Object clone() throws CloneNotSupportedException {
		// This is to delegate the implementation to subclasses.
		return doClone();
	}
	
	public abstract Object doClone() throws CloneNotSupportedException;

	@Override
	public void dispose() {
		this.status = Status.STATUS_SHUTDOWN;
		// It's also possible to add more clean up operations in subclasses.
	}

	@Override
	public void notifyElementEvicted(Ehcache cache, Element element) {
		// As persistence storage, it doesn't care about element eviction.
	}

	@Override
	public void notifyElementExpired(Ehcache cache, Element element) {
		// As persistence storage, it doesn't care about expired elements.
	}
	
	/**
	 * The method generates key for use in S3 as String by accepting key itself.
	 * 
	 * @param o			The key as Object.
	 * @return			The key as String used for Amazon S3.
	 * @see				org.chenwang.projects.ehcacheaws.AmazonS3AwareKey
	 */
	protected String generateKey(Object o) {
		String key = null;
		if (o instanceof AmazonS3AwareKey) {
			// It uses defined key for S3 if available.
			key = ((AmazonS3AwareKey) o).keyToS3();
		}
		else {
			// By default it uses toString() to form the key.
			key = o.toString();
		}
		return this.pathName + this.pathSeparator + key;
	}

	/**
	 * The method generates key as String, by taking into consideration of keys
	 * implementing AmazonS3AwareKey or not. Please note that the key returned 
	 * by the method includes path name and separator from configuration so that
	 * the key is ready to be used as S3 key.
	 * 
	 * @param element	The cache element.
	 * @return			The key as String used for Amazon S3.
	 * @see				org.chenwang.projects.ehcacheaws.AmazonS3AwareKey
	 */
	protected String generateKey(Element element) {
		return this.generateKey(element.getObjectKey());
	}
	
	/**
	 * The method generates value as String, by taking into consideration of 
	 * values implementing AmazonS3AwareValue or not. The value returned will be
	 * stored to S3. 
	 * 
	 * @param element	The cache element.
	 * @return			The value as String used for Amazon S3.
	 * @see				org.chenwang.projects.ehcacheaws.AmazonS3AwareValue
	 */
	protected String generateValue(Element element) {
		String value = null;
		if (element.getObjectValue() instanceof AmazonS3AwareValue) {
			// It uses defined value for S3 if available.
			value = ((AmazonS3AwareValue) element.getObjectValue()).valueToS3();
		}
		else {
			// By default it uses toString() to form the value.
			value = element.getObjectValue().toString();
		}
		return value;
	}
}
